fix: normalize lazy() module-url paths to forward slashes on Windows#263
Open
rhengles wants to merge 1 commit into
Open
fix: normalize lazy() module-url paths to forward slashes on Windows#263rhengles wants to merge 1 commit into
rhengles wants to merge 1 commit into
Conversation
The `solid-lazy-module-url` transform appends the resolved module path as the 2nd argument to `lazy(() => import(...))` using `path.relative`, which yields backslashes on Windows. The injected `"src\components\App.tsx"` is an invalid escape sequence that broke dev/build for any `lazy()` route on Windows. Add a `normalizeLazyModulePath` helper, a node:test unit suite for it, and run those unit tests from `scripts/test-examples.ts` (so `pnpm test` covers them). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: bb9f9bb The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: normalize
lazy()module-url paths to forward slashes on WindowsProblem
The
solid-lazy-module-urlbabel pass detectslazy(() => import("specifier"))and injects a placeholder as a 2nd argument; the
transformhook then resolvesthat placeholder to the module's project-relative path and substitutes it back
into the emitted source.
The path is built with
path.relative, which returns OS-native separators.On Windows that means backslashes, and the result is spliced straight back into
JS source as a string literal:
\c,\A, etc. are invalid string escape sequences, so the file fails toparse. In practice this breaks dev and build for any
lazy()route onWindows (the downstream esbuild/rolldown transform throws
Invalid escape sequence/Transform failed). POSIX is unaffected becausepath.relativealready returns forward slashes there — which is why it hasgone unnoticed.
Where
src/index.ts, in the lazy-placeholder resolution loop:No normalization is applied before the path is embedded back into source.
Fix
Normalize the resolved path to POSIX separators before embedding it. The path
is only ever used as a module-url string in generated JS, so forward slashes
are always correct (and match what the rest of Vite emits).
A small pure helper is added to
src/lazy-module-url.ts(its natural home,alongside
LAZY_PLACEHOLDER_PREFIX):and the call site becomes:
That is the entire behavioral change — one helper plus one wrapped call.
Tests
test/lazy-module-url.test.tscovers the helper with the built-innode:testrunner (no new dependencies):Why a unit test of the helper, and not an example/e2e test
The bug is OS-specific: it only reproduces when
path.relativereturnsbackslashes, i.e. on Windows. The existing example + Cypress/Vitest suites run
on Linux CI runners, where
path.relativealready yields forward slashes —so an example-based test could never fail for this bug regardless of the fix.
A pure unit test on the normalization function is deterministic on every
OS: it feeds a backslash path in and asserts forward slashes out, so it guards
the regression on the Linux CI too.
How it's wired (and why this way)
There is intentionally no new
package.jsonscript. The unit suite is runfrom the existing
scripts/test-examples.ts(already invoked bypnpm test),before the example builds, so:
Rationale:
pnpm testalready drives the whole suite; foldingthe unit tests in keeps one command and means CI (
e2e.yml→pnpm run test)picks them up with no workflow changes.
pnpm install+ build per example.spawn(..., { stdio: 'inherit' })lets the TAP outputpass straight through, and a non-zero exit rejects so the run aborts (and the
child is tracked in
activeProcessesfor the existing cleanup path).node:testis built in. Node strips theTypeScript types itself (CI runs Node 23, which does this unflagged; the
test/dir is outsidetsconfigincludeand the rollup entry, so it neverleaks into
dist).Placement / CI note
This targets
nextbecauselazy()module-url resolution only existsthere. Heads-up: the workflows currently trigger on
branches: [main]only, soa
next-targeted PR may not auto-run CI untilnextis added to the triggers(left untouched here — maintainer call).
Verification
node scripts/test-examples.ts→Running unit tests...→ 4/4 pass →proceeds to
Testing vite-3....pnpm build→ exit 0; bundle containsnormalizeLazyModulePath(path.relative(projectRoot, cleanId)).lazy()route 500'd in dev withInvalid escape sequencebefore the change, renders cleanly after.